package com.easylinkin.linkappapi.webcammanage.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.airconditioner.entity.AirconditionDevice;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.common.utils.excel.ExcelConstant;
import com.easylinkin.linkappapi.common.utils.excel.ExcelTools;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.elasticsearch.entity.ESconfig;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.webcammanage.entity.DataAnalystBean;
import com.easylinkin.linkappapi.webcammanage.entity.DataAnalystBeanExcel;
import com.easylinkin.linkappapi.webcammanage.entity.QueryDataCondition;
import com.easylinkin.linkappapi.webcammanage.mapper.DataAnalystMapper;
import com.easylinkin.linkappapi.webcammanage.service.DataAnalystESService;
import com.easylinkin.linkappapi.webcammanage.util.YYSHDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class DataAnalystESServiceImpl extends ServiceImpl<DataAnalystMapper, DataAnalystBean> implements DataAnalystESService {

    private ESconfig eSconfig;

//    private final static String indexStrES = "testlqh";//dev
    private final static String indexStrES = "yysh";//test
    private final static String dataAnalystES = "data_analyst";

    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;

    @Autowired
    public void setESconfig(ESconfig eSconfig) {
        this.eSconfig = eSconfig;
    }

    @Override
    public Page<DataAnalystBean> selectDataAnalystPage(Page page, QueryDataCondition queryDataCondition) {
        Assert.notNull(page, "分页数据不能为空");
        RestHighLevelClient rhlClient = eSconfig.getFactory().getRhlClient();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        LinkappUser currentUser = linkappUserContextProducer.getCurrent();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        MatchQueryBuilder tenantIdQuery = QueryBuilders.matchQuery("tenantId", currentUser.getTenantId());
        if(!StringUtils.isEmpty(queryDataCondition.getCreateTimeStart()) || !StringUtils.isEmpty(queryDataCondition.getCreateTimeEnd())){
            RangeQueryBuilder createTime = QueryBuilders.rangeQuery("createTime");
            if(!StringUtils.isEmpty(queryDataCondition.getCreateTimeStart())){
                createTime.gte(queryDataCondition.getCreateTimeStart());
            }
            if(!StringUtils.isEmpty(queryDataCondition.getCreateTimeEnd())){
                createTime.lt(queryDataCondition.getCreateTimeEnd());
            }
            boolQueryBuilder.must(createTime);
        }
        boolQueryBuilder.must(tenantIdQuery);
        searchSourceBuilder.query(boolQueryBuilder).sort("createTime", SortOrder.DESC)
                .from((int) ((page.getCurrent() -1) * page.getSize()))
                .size((int) page.getSize());
        SearchRequest searchRequest = new SearchRequest(indexStrES).types(dataAnalystES).source(searchSourceBuilder);
        SearchResponse searchResponse = null;
        try {
            log.info("查询ES请求数据：" + searchRequest.toString());
            searchResponse = rhlClient.search(searchRequest, RequestOptions.DEFAULT);

        } catch (Exception e) {
            log.error("ES查询异常" + e.getMessage());
        }
        if (null == searchResponse) {
            return null;
        }

        SearchHit[] hits = searchResponse.getHits().getHits();
        List<DataAnalystBean> dataAnalystBeanList = new ArrayList<DataAnalystBean>();
        for (SearchHit hit : hits) {
            DataAnalystBean dab = JSONObject.parseObject(hit.getSourceAsString(), DataAnalystBean.class);
            dataAnalystBeanList.add(dab);
        }

        //手动设置总记录
        page.setTotal(searchResponse.getHits().totalHits);
        page.setRecords(dataAnalystBeanList);
        return page;
    }

    @Override
    public String[] insertDataAnalystRecord(DataAnalystBean dataAnalystBean) {
        Assert.isTrue(!StringUtils.isEmpty(dataAnalystBean.getLocation()), "位置参数不能为空");
        List<DataAnalystBean> dataAnalystBeanList = new ArrayList<>();
        dataAnalystBeanList.add(dataAnalystBean);
        String[] aBoolean = insertDataAnalystRecord(dataAnalystBeanList);
        return aBoolean;
    }

    @Override
    public String[] insertDataAnalystRecord(List<DataAnalystBean> dataAnalystBeanList) {
        String[] results = new String[3];
        //使用Bulk后期方便改为批量导入
        List<String> ids = new ArrayList<>();
        RestHighLevelClient hclient = eSconfig.getFactory().getRhlClient();
        BulkRequest request = new BulkRequest();
        LinkappUser currentUser = linkappUserContextProducer.getCurrent();

        for (DataAnalystBean dataAnalystBean:
                dataAnalystBeanList) {
            if(StringUtils.isEmpty(dataAnalystBean.getLocation())){
                results[0]= "1";
                results[1]= "请填写位置信息";
                return results;
            }
            //记录时间为空则默认为系统时间
            if(StringUtils.isEmpty(dataAnalystBean.getCreateTime())){
                dataAnalystBean.setCreateTime(DateUtil.getCurrentDateStr(DateUtil.DATE_TIME_FORMAT_DEFAULT));
            }else{
                boolean b = YYSHDateUtil.checkDateFormat(dataAnalystBean.getCreateTime());
                if(!b){
                    results[0]= "1";
                    results[1]= "创建时间格式错误";
                    return results;
                }
            }
            //压榨时间为空则默认为系统时间
            if(StringUtils.isEmpty(dataAnalystBean.getPressTime())){
                dataAnalystBean.setPressTime(DateUtil.getCurrentDateStr(DateUtil.DATE_TIME_FORMAT_DEFAULT));
            }else{
                boolean b = YYSHDateUtil.checkDateFormat(dataAnalystBean.getPressTime());
                if(!b){
                    results[0]= "1";
                    results[1]= "压榨时间格式错误";
                    return results;
                }
            }
            //进料时间为空则默认为系统时间
            if(StringUtils.isEmpty(dataAnalystBean.getFeedstockTime())){
                dataAnalystBean.setFeedstockTime(DateUtil.getCurrentDateStr(DateUtil.DATE_TIME_FORMAT_DEFAULT));
            }else{
                boolean b = YYSHDateUtil.checkDateFormat(dataAnalystBean.getFeedstockTime());
                if(!b){
                    results[0]= "1";
                    results[1]= "进料时间格式错误";
                    return results;
                }
            }
            if(dataAnalystBean.getPainiNum() == null ){
                dataAnalystBean.setPainiNum(0.00);
            }else {
                if(YYSHDateUtil.match(YYSHDateUtil.zhengFloatNumRegex, dataAnalystBean.getPainiNum().toString())){
                    results[0]= "1";
                    results[1]= "排泥量格式错误";
                    return results;
                }
            }
            if(dataAnalystBean.getJiayaoNum() == null ){
                dataAnalystBean.setJiayaoNum(0.00);
            }else {
                if(YYSHDateUtil.match(YYSHDateUtil.zhengFloatNumRegex, dataAnalystBean.getJiayaoNum().toString())){
                    results[0]= "1";
                    results[1]= "加药量格式错误";
                    return results;
                }
            }
            if(dataAnalystBean.getJinyaoNum() == null ){
                dataAnalystBean.setJinyaoNum(0.00);
            }else {
                if(YYSHDateUtil.match(YYSHDateUtil.zhengFloatNumRegex, dataAnalystBean.getJinyaoNum().toString())){
                    results[0]= "1";
                    results[1]= "进药量格式错误";
                    return results;
                }
            }
            dataAnalystBean.setUpdateTime(DateUtil.getCurrentDateStr(DateUtil.DATE_TIME_FORMAT_DEFAULT));
            dataAnalystBean.setStatus(1);
            String id = UUID.randomUUID().toString().replaceAll("-", "");
            dataAnalystBean.setId(id);
            dataAnalystBean.setTenantId(currentUser.getTenantId());
            ids.add(id);
            String jsonString;

            //批量导入使用，正常insert不使用
            if(StrUtil.isNotEmpty(dataAnalystBean.getDevStatusStr())){
                if("正常".equals(dataAnalystBean.getDevStatusStr())){
                    dataAnalystBean.setDevStatus(1);
                }else if("异常".equals(dataAnalystBean.getDevStatusStr())){
                    dataAnalystBean.setDevStatus(2);
                }
            }
            jsonString = JSON.toJSONString(dataAnalystBean);
            log.info("数据入录insert json str =" + jsonString);
            request.add(new IndexRequest(indexStrES).type(dataAnalystES).id(dataAnalystBean.getId()).source(jsonString, XContentType.JSON));
        }

         try {
            BulkResponse bulkResponse = hclient.bulk(request, RequestOptions.DEFAULT);
            if (bulkResponse.hasFailures()) {
                for (BulkItemResponse bulkItemResponse : bulkResponse) {
                    if (bulkItemResponse.isFailed()) {
                        //检索失败操作的失败
                        BulkItemResponse.Failure failure = bulkItemResponse.getFailure();
                        log.error("插入索引为{}id为{}ES动作失败!", failure.getIndex(), failure.getId());
                        throw new Exception();
                    }
                }
            }
        } catch (Exception e) {
            log.error("插入索引为{}的ES动作失败{}!", indexStrES, e);
             results[0]= "1";
             results[1]= "保存异常";
             return results;
        }
        results[0]= "0";
        results[1]= "保存成功";
        results[2]= dataAnalystBeanList.size()>0 ? JSON.toJSONString(dataAnalystBeanList.get(0)) : null;
        return results;
    }

    @Override
    public Boolean deleteDataAnalystRecord(String id) {
        DeleteRequest deleteRequest = new DeleteRequest(indexStrES, dataAnalystES, id);
        // 操作ES
        DeleteResponse deleteResponse = null;
        RestHighLevelClient rhlClient = eSconfig.getFactory().getRhlClient();
        try {
            deleteResponse = rhlClient.delete(deleteRequest, RequestOptions.DEFAULT);
            if(deleteResponse.status().getStatus() == 200){
                return true;
            }else {
                return false;
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return true;
    }

    @Override
    public Boolean updateDataAnalystRecord(DataAnalystBean dataAnalystBean) {
        Assert.isTrue(!StringUtils.isEmpty(dataAnalystBean.getId()), "id 不能为空");
        Assert.isTrue(!StringUtils.isEmpty(dataAnalystBean.getLocation()), "位置参数不能为空");
        dataAnalystBean.setUpdateTime(DateUtil.getCurrentDateStr(DateUtil.DATE_TIME_FORMAT_DEFAULT));
        UpdateRequest updateRequest = new UpdateRequest(indexStrES, dataAnalystES, dataAnalystBean.getId());
        updateRequest.doc(JSON.toJSONString(dataAnalystBean), XContentType.JSON);
        RestHighLevelClient rhlClient = eSconfig.getFactory().getRhlClient();
        try {
            UpdateResponse update = rhlClient.update(updateRequest, RequestOptions.DEFAULT);
            if(update.status().getStatus() == 200){
                return true;
            }else {
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public DataAnalystBean getDataAnalystInfoByCondition(DataAnalystBean dataAnalystBean) {
        return null;
    }

    @Override
    public String[] importYYSHData(MultipartFile file) {
        String[] result = new String[2];
        InputStream inputStream = null;
        try {
            Map<String, String> headerMap = new HashMap<String, String>();
            headerMap.put("记录时间", "createTime");
            headerMap.put("位置", "location");
            headerMap.put("排泥量", "painiNum");
            headerMap.put("设备状态", "devStatusStr");
            headerMap.put("加药量", "jiayaoNum");
            headerMap.put("进药量", "jinyaoNum");
            headerMap.put("进料时间", "feedstockTime");
            headerMap.put("压榨时间", "pressTime");
            headerMap.put("备注", "remarks");
            inputStream = file.getInputStream();

            List<DataAnalystBeanExcel> dataAnalystBeansExcel = ExcelTools.readExcel(inputStream, ExcelConstant.XLS, headerMap, DataAnalystBeanExcel.class, null);
            if(dataAnalystBeansExcel == null || dataAnalystBeansExcel.size() <= 0){
                result[0]= "1";
                result[1]= "无记录";
                return result;
            }
            LinkappUser currentUser = linkappUserContextProducer.getCurrent();
            List<DataAnalystBean> dataAnalystBeans = new ArrayList<DataAnalystBean>();
            for (DataAnalystBeanExcel adb:
                dataAnalystBeansExcel) {
                DataAnalystBean  a = new DataAnalystBean();
                a.setCreateTime(adb.getCreateTime());
                a.setLocation(adb.getLocation());
                a.setPainiNum(Double.parseDouble(adb.getPainiNum()));
                a.setDevStatusStr(adb.getDevStatusStr());
                a.setJiayaoNum(Double.parseDouble(adb.getJiayaoNum()));
                a.setJinyaoNum(Double.parseDouble(adb.getJinyaoNum()));
                a.setFeedstockTime(adb.getFeedstockTime());
                a.setPressTime(adb.getPressTime());
                a.setRemarks(adb.getRemarks());
                a.setTenantId(currentUser.getTenantId());
                dataAnalystBeans.add(a);
            }

            String[] aBoolean = insertDataAnalystRecord(dataAnalystBeans);
            return aBoolean;
        } catch (Exception e) {
            e.printStackTrace();
            result[0]= "1";
            result[1]= "数据可能未识别到";
        }
        return result;
    }

    @Override
    public void exportYYSHData(QueryDataCondition queryParams, HttpServletRequest request, HttpServletResponse response) {
        RestHighLevelClient rhlClient = eSconfig.getFactory().getRhlClient();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        LinkappUser currentUser = linkappUserContextProducer.getCurrent();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        MatchQueryBuilder tenantIdQuery = QueryBuilders.matchQuery("tenantId", currentUser.getTenantId());
        boolQueryBuilder.must(tenantIdQuery);
        if(!StringUtils.isEmpty(queryParams.getCreateTimeStart()) || !StringUtils.isEmpty(queryParams.getCreateTimeEnd())){
            RangeQueryBuilder createTime = QueryBuilders.rangeQuery("createTime");
            if(!StringUtils.isEmpty(queryParams.getCreateTimeStart())){
                createTime.gte(queryParams.getCreateTimeStart());
            }
            if(!StringUtils.isEmpty(queryParams.getCreateTimeEnd())){
                createTime.lt(queryParams.getCreateTimeEnd());
            }
            boolQueryBuilder.must(createTime);
        }
        searchSourceBuilder.query(boolQueryBuilder).sort("createTime", SortOrder.DESC).size(10000);
        SearchRequest searchRequest = new SearchRequest(indexStrES).types(dataAnalystES).source(searchSourceBuilder);
        SearchResponse searchResponse = null;
        try {
            log.info("查询ES请求数据：" + searchRequest.toString());
            searchResponse = rhlClient.search(searchRequest, RequestOptions.DEFAULT);

        } catch (Exception e) {
            log.error("ES查询异常" + e.getMessage());
        }

        if (null == searchResponse) {
            log.info("ES查询结果返回的对象为空！！！！");
            return ;
        }

        SearchHit[] hits = searchResponse.getHits().getHits();
        List<DataAnalystBean> dataAnalystBeanList = new ArrayList<DataAnalystBean>();
        for (SearchHit hit : hits) {
            DataAnalystBean dab = JSONObject.parseObject(hit.getSourceAsString(), DataAnalystBean.class);
            if(dab.getDevStatus() != null && dab.getDevStatus().equals(1)){
                dab.setDevStatusStr("正常");
            }else {
                dab.setDevStatusStr("异常");
            }
            dataAnalystBeanList.add(dab);
        }

        if(dataAnalystBeanList == null || dataAnalystBeanList.size() <= 0){
            log.info("无数据, 该范围内无数据");
            return ;
        }
        List<String> stringList = new ArrayList<String>();

        //  表头
        String keyValue = "记录时间:createTime,位置:location,排泥量:painiNum,设备状态:devStatusStr,加药量:jiayaoNum,进药量:jinyaoNum,进料时间:feedstockTime,压榨时间:pressTime,备注:remarks";

        String title = "岳阳石化数据列表";
        String fileName = title + ".xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);
            ExcelTools.exportBankExcelV2(outputStream, keyValue, dataAnalystBeanList, ExcelConstant.XLS, title, stringList);
            response.flushBuffer();
            outputStream.close();
        } catch (IOException e) {
            log.error("excel导出失败");
            throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
        } catch (Exception e) {
            log.error("excel导出失败");
            throw new RuntimeException("excel导出失败！" + e.getMessage());
        }
    }

    @Override
    public void exportYYSHTemplateFile(HttpServletRequest request, HttpServletResponse response) {
        String title = "岳阳石化录入数据表";
        String fileName = title + ".xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);

            String keyValue = "记录时间:createTime,位置:location,排泥量:painiNum,设备状态:devStatusStr,加药量:jiayaoNum,进药量:jinyaoNum,进料时间:feedstockTime,压榨时间:pressTime,备注:remarks";
            ExcelTools
                    .exportExcelLqh(outputStream, keyValue, inits(), ExcelConstant.XLS,
                            null);
            response.flushBuffer();
            outputStream.close();
        } catch (IOException e) {
            log.error("excel导出失败");
            throw new RuntimeException("excel导出失败！IOException异常");
        } catch (Exception e) {
            log.error("excel导出失败");
            throw new RuntimeException("excel导出失败！");
        }
    }

    public List<DataAnalystBean> inits(){
        return Arrays.asList(new DataAnalystBean()
                .setCreateTime("2021-11-12 11:47:02")
                .setLocation("岳阳东站")
                .setPainiNum(1.3)
                .setDevStatusStr("正常")
                .setJiayaoNum(2.6)
                .setJinyaoNum(3.1)
                .setFeedstockTime("2021-11-12 10:47:02")
                .setPressTime("2021-11-12 09:31:02")
                .setRemarks("备注填写"),
                new DataAnalystBean()
                        .setCreateTime("2021-11-11 11:47:02")
                        .setLocation("岳阳书院")
                        .setPainiNum(2.3)
                        .setDevStatusStr("异常")
                        .setJiayaoNum(4.6)
                        .setJinyaoNum(1.1)
                        .setFeedstockTime("2021-11-10 10:47:02")
                        .setPressTime("2021-11-09 09:31:02")
                        .setRemarks("备注填写")
        );
    }

    /*@Override
    public void exportYYSHTemplateFile(HttpServletRequest request, HttpServletResponse response) {
        String templateLocalPath = DataAnalystESServiceImpl.class.getResource("/").getPath() + "templates/yysh/yysh_data_import.xls";
        log.info("old   模板文件目录：" + templateLocalPath);
        templateLocalPath = templateLocalPath.replace("/D:", "D:");
        log.info("new   模板文件目录：" + templateLocalPath);
        String fileName = "岳阳石化数据导入模板.xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);
            FileInputStream fis = new FileInputStream(new File(templateLocalPath));
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = fis.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
            response.flushBuffer();
            fis.close();
            outputStream.close();
        } catch (IOException e) {
            log.error("excel导出失败");
            throw new RuntimeException("excel导出失败！IOException异常");
        } catch (Exception e) {
            log.error("excel导出失败");
            throw new RuntimeException("excel导出失败！");
        }
    }*/

}
